﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace Dotway.WPF.Effects
{
    public class GrayscaleEffect : ShaderEffect
    {
        #region Fields

        private static PixelShader pixelShader = new PixelShader();

        #endregion Fields
        #region Constructors

        static GrayscaleEffect()
        {
            pixelShader.UriSource = Global.MakePackUri("GrayscaleEffect.ps");
        }

        public GrayscaleEffect()
        {
            this.PixelShader = pixelShader;

            // Update each DependencyProperty that's registered with a shader register.  This
            // is needed to ensure the shader gets sent the proper default value.
            UpdateShaderValue(InputProperty);
            UpdateShaderValue(DesaturationFactorProperty);
        }

        #endregion Constructors
        #region Properties

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(GrayscaleEffect), 0);
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }


        public static readonly DependencyProperty DesaturationFactorProperty = DependencyProperty.Register("DesaturationFactor", typeof(double), typeof(GrayscaleEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(0), CoerceDesaturationFactor));

        /// <summary>
        /// A value between 0.0-1.0. 0.0 represents a grayscale image and 1.0 a color image.
        /// Use this property to gradually desaturate and image e.g. in an animation.
        /// </summary>
        public double DesaturationFactor
        {
            get { return (double)GetValue(DesaturationFactorProperty); }
            set { SetValue(DesaturationFactorProperty, value); }
        }

        private static object CoerceDesaturationFactor(DependencyObject d, object value)
        {
            GrayscaleEffect effect = (GrayscaleEffect)d;
            double newFactor = (double)value;

            if (newFactor < 0.0 || newFactor > 1.0)
            {
                return effect.DesaturationFactor;
            }

            return newFactor;
        }               

        #endregion Properties       
    }
}
